/**
 * 调度任务类的基类，增加分布式环境中的调度互斥特性
 */
package com.hanhai.common.task;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hanhai.common.zookeeper.ZookeeperLock;

/**
 * @author leiruiqi@hanhai.com
 *
 */
public abstract class BaseTask {

	protected final Logger logger = LoggerFactory.getLogger(BaseTask.class);
	
	
	@Resource
	private ZookeeperLock zookeeperLock;
	
	/**
	 * @param bizKey   //任务的bizKey
	 * @return
	 */
	public boolean doTaskSynchronous(String bizKey){
		boolean bool = zookeeperLock.simplelock(bizKey);
		return bool;
	}
	
	public void doRmoveTaskSynchronous(String bizKey){
		logger.info("doRmoveTaskSynchronous,bizKey="+bizKey);
		zookeeperLock.simpleUnlock(bizKey);
	}

	
	/**
	 * 调度任务在分布式环境的中互斥的key ，全局唯一
	 * @return
	 */
	public abstract String getBizKey();
	
	/**
	 * 默认的业务逻辑实现
	 */
	public abstract void doDefaultBiz();
	
	
	/**
	 * 返回默认最少需要互斥的时间间隔
	 * @return
	 */
	public abstract Integer lockTime();
	
	/**
	 * 为默认业务逻辑方法doDefaultBiz()实现互斥的执行,确保在分布式环境中不需会出现重复调度
	 */
	public void doDefaultSynBiz(){
		boolean bool = doTaskSynchronous(getBizKey());
		if(!bool){
			return;
		}
		Long startTime = System.currentTimeMillis();
		Long endTime;
		try {
			doDefaultBiz();
			endTime = System.currentTimeMillis();
			logger.info("task "+getBizKey());
			
		} catch (Exception e) {
			logger.error("",e);
			endTime = System.currentTimeMillis();
		}
		
		holdForOverTime(startTime,lockTime());
		doRmoveTaskSynchronous(getBizKey());
	}

	/**
	 * 一个自动计算最大等待时间的方法，等待足够时间才会退出，用于控制互斥持续时间
	 * @param startTime  互斥开始的时间
	 * @param holdSecends	互斥持续的时间，单位是秒
	 */
	public void holdForOverTime(Long startTime,Integer holdSecends){
		//最大等待毫秒数
		Long maxWaitTime = 10000L;
		Long currentTime = System.currentTimeMillis();
		Long usedTime =  currentTime - startTime;
		Long limitTime = holdSecends*1000L-usedTime;
		if(limitTime>=0){
			if(limitTime>maxWaitTime){
				limitTime = maxWaitTime;
			}
			try {
				Thread.sleep(limitTime);
			} catch (InterruptedException e) {
				logger.error("",e);
			}
		}
	}
}
